import base64
import pickle

from django.shortcuts import render
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView

# w为了生成短信验证码需要一个模块
from random import randint

# 为了与redis数据库建立链接
from django_redis import get_redis_connection
from rest_framework_jwt.views import ObtainJSONWebToken

from carts.utils import merge_cart_cookie_to_redis
from goods.models import SKU
from goods.serializers import SKUSerializers
from meiduo_mall.libs.yuntongxun.sms import CCP

from rest_framework.generics import CreateAPIView, RetrieveAPIView, UpdateAPIView, GenericAPIView

from users import serializers
from users.serializers import CreateUserSerializer, EmailSerializer, VerifyEmailSerializer, \
    AddUserBrowsingHistorySerializer
from celery_tasks.sms.tasks import send_sms_code
from users.models import User

from rest_framework.permissions import IsAuthenticated


# Create your views here.


# get sms_code/mobile  ok



class SMSCodeView(APIView):
    def get(self, request, mobile):
        # 判断60s
        # 建立链接
        conn = get_redis_connection('verify')
        flag = conn.get('sms_flag_%s' % mobile)
        if flag:
            return Response({'message': 'error'}, status=401)

        # 生成短信验证码
        sms_code = '%06d' % randint(0, 999999)
        print(sms_code)

        # 保存到redis缓存
        # 建立链接

        # 写入数据库 通过管道的方式
        pl = conn.pipeline()
        pl.setex('sms_code_%s' % mobile, 300, sms_code)
        pl.setex('sms_flag_%s' % mobile, 60, 1)
        pl.execute()

        # 发送短信
        # 由类生成对象
        # ccp = CCP()
        # ccp.send_template_sms(mobile, [sms_code, '5'], 1)
        send_sms_code.delay(mobile, sms_code)
        print(sms_code)

        # 返回结果
        return Response({'message': 'ok'})


# url(r^usernames/(?P<username>\2{5,20})/count/$', views.UsernameCountView.as_view()),
class UsernameCountView(APIView):
    """
    用户名数量
    """

    def get(self, request, username):
        """
        获取指定用户名数量
        :param request:
        :param username:
        :return:
        """
        # 查询用户数量
        count = User.objects.filter(username=username).count()

        data = {
            'username': username,
            'count': count
        }

        # 返回查询的数量给前段（判断用户是否注册过）
        return Response(data)


# url(r'^mobiles/(?P<mobile>1[3-9]\d{9})/count/$', views.MobileCountView.as_view()),
class MobileCountView(APIView):
    """
    手机号数量
    """

    def get(self, request, mobile):
        """
        获取指定手机号数量
        """
        count = User.objects.filter(mobile=mobile).count()

        data = {
            'mobile': mobile,
            'count': count
        }

        return Response(data)


class UserView(CreateAPIView):
    # 指定一个序列化器
    serializer_class = CreateUserSerializer


# 注意:访问视图必须要求用户已经通认证(即登录之后)
class UserDetailView(RetrieveAPIView):
    """用户详情"""
    serializer_class = serializers.UserDetailSerializer
    # 指定权限
    permission_classes = [IsAuthenticated]

    # 重写get_object方法返回指定数据对象
    def get_object(self):
        print(self.request.user)

        return self.request.user


# 用于保存用户的邮箱信息,注意需要用户登陆人中通过后
# UpdataAPIView里面有有put方法(更新数据)
class EmailView(UpdateAPIView):
    """保存用户邮箱"""
    permission_classes = [IsAuthenticated]
    # 指定序列化器
    serializer_class = serializers.EmailSerializer

    # def put(self, request, *args, **kwargs):
    #     ser = EmailSerializer(request.user, data=request.data, context={'request':request, 'mobile':13570882306})
    #
    #     ser.is_valid()
    #     ser.save()
    #     return Response(ser.data)

    def get_object(self, *args, **kwargs):
        return self.request.user


# 验证邮箱链接
class VerifyEmailView(GenericAPIView):
    serializer_class = VerifyEmailSerializer
    """邮箱验证"""

    def get(self, request):
        # 获取用户数据
        data = request.query_params
        # 数据验证
        ser = self.get_serializer(data=data)
        ser.is_valid()
        print(ser.errors)
        # 更新用户邮箱状态
        data = ser.validated_data['data']
        id = data['id']
        username = data['username']
        try:
            user = User.objects.get(id=id, username=username)
        except:
            return Response({'errors': '用户不存在'}, status=400)

        user.email_active = True
        user.save()

        # 结果返回
        return Response({'email_active': True})


class AddUserBrowsingHistoryView(CreateAPIView):
    """
    保存用户浏览历史记录
    """
    serializer_class = AddUserBrowsingHistorySerializer
    permission_classes = [IsAuthenticated]

    # list数据是查询mysql数据库,但是浏览记录保存的数据在redis数据库中,所以需要重写get方法
    def get(self, request):
        """获取浏览记录历史数据"""
        user_id = request.user.id

        redis_conn = get_redis_connection("history")
        sku_id_list = redis_conn.lrange("history_%s" % user_id, 0, 4)

        skus = []
        # 为了保持查询出的顺序与用户的浏览历史保存顺序一致
        for sku_id in sku_id_list:
            sku = SKU.objects.get(id=sku_id)
            skus.append(sku)

        # 序列化返回, 在goods中已经定义了一个直接拿过来用
        ser = SKUSerializers(skus, many=True)

        return Response(ser.data)


class UserAuthorizeView(ObtainJSONWebToken):
    # 重写登录业务逻辑
    def post(self, request, *args, **kwargs):

        response = super().post(request, *args, **kwargs)

        # 仿照drf jwt扩展对于用户登录的认证方式,判断用户是否认证登录成功
        # 如果用户登录认证成功, 则合并购物车

        serializer = self.get_serializer(data=request.data)
        if serializer.is_valid():
            user = serializer.validated_data.get('user')
            response = merge_cart_cookie_to_redis(request, user, response)

        return response















